#include "include/EchoServer.hpp"
#include "include/businessService.hpp"
#include "include/UserMannger.hpp"
#include "include/MySQLClient.hpp"
#include <sys/stat.h>
#include <sys/types.h>
#include <sstream>
using std::stringstream;

void EchoServer::onClose(TcpConnectionPtr pconn){
    //删除连接断开的用户
    UserMannger::getUseMananger()->delUser(pconn->fd());
    if(_ffmpegs.count(pconn->fd())>0){
        cout<<"onClose address : "<<(void *)&_ffmpegs[pconn->fd()]<<endl; 
        _ffmpegs[pconn->fd()].stop();
    }

    stringstream sstr;
    sstr.clear();
    sstr<<pconn->toString()<<" has closed."<<endl;
    LOG_INFO(sstr.str().c_str());
    LOG_DEBUG(sstr.str().c_str());
}

void EchoServer::onConnect(TcpConnectionPtr pconn){
    stringstream sstr;
    sstr.clear();
    sstr<< pconn->toString() << " has connected successfully.\n";
    LOG_INFO(sstr.str().c_str());
    LOG_DEBUG(sstr.str().c_str());
}

void EchoServer::onMessage(TcpConnectionPtr pconn){
    Packet packet  = pconn->recvPacket();
    LOG_INFO(packet._msg.c_str());
    LOG_DEBUG(packet._msg.c_str());
    switch(packet._type){
    case TTLS1:
        _pool.addTask(new UserLoginSection1(move(packet),*pconn.get()));
        break;
    case TTLS2:
        _pool.addTask(new UserLoginSection2(move(packet),*pconn.get()));
        break;
    case TTR1:
        _pool.addTask(new UserRegister1(move(packet),*pconn.get()));
        break;
    case TTR2:
        _pool.addTask(new UserRegister2(move(packet),*pconn.get()));
        break;
    case TASK_GET_CODEC_PARAMS:
        _pool.addTask(new SendCodecParams(move(packet),*pconn.get()));
        break;
    case TASK_GET_AVPACKET:
        if(_ffmpegs.count(pconn->fd())==0){
            RtspDecoder rtd(packet._msg);
            _ffmpegs[pconn->fd()] = rtd;
        }
        _lpool.addTask(new SendAVPacket(*pconn.get(),&_ffmpegs[pconn->fd()],_ffmpegs));
        break;
    case TASK_STOP_RTMP:
        _ffmpegs[pconn->fd()].stop();
        break;
    case TASK_PTZ_CONTROL:
        _pool.addTask(new SendPTZControl(std::move(packet),*pconn.get()));
        break;
    case TASK_GET_PLAYBACK_RANGE:
        _pool.addTask(new SendPlayList(std::move(packet),*pconn.get()));
        break;
    case TASK_GET_PALYBACK_CODEC_PARAMS:
        _pool.addTask(new SendPlayBackCodecParams(std::move(packet),*pconn.get()));
        break;
    case TASK_GET_PLAYBACK_AVPACKET:
        if(_ffmpegs.count(pconn->fd())==0){
            RtspDecoder rtd(packet._msg);
            _ffmpegs[pconn->fd()] = rtd;
        }
        _lpool.addTask(new SendPlayBackAVPacket(std::move(packet),*pconn.get(),&_ffmpegs[pconn->fd()],_ffmpegs));
        break;
    case TASK_STM32_SENSORS:
        _pool.addTask(new SendStm32Infm(std::move(packet)));
        break;
    };
}

void EchoServer::start(){
    _pool.start();
    _lpool.start();
    MySQLClient SQLConn;
    vector<vector<string >> data =SQLConn.readOperationQuery("SELECT camera_id,camera_channels,rtmp,camera_serial_no FROM camera");
    SQLConn.dump(data);

    //开始录像
    for(int i =1 ;i< (int)data.size();++i){
        int channels = std::atoi(data[i][1].c_str());
        int cameraId = std::atoi(data[i][0].c_str());
        LOG_DEBUG(("channels: "+data[i][1]).c_str());
        string path ="./videos/"+data[i][3]; 
        if(mkdir(path.c_str(),0755)!=0){
            if(errno !=EEXIST){
                LOG_ERROR(("direct create is failed. "+path).c_str());
                exit(1);
            }
        }//创建对应序列号的文件夹

        for(int j = 0;j< channels;++j){
           const string & path_temp =path+"/channel"+to_string(j);
            if(mkdir(path_temp.c_str(),0755)!=0){
                if(errno !=EEXIST){
                    LOG_ERROR(("direct create is failed. "+path_temp).c_str());
                    exit(1);
                }
            }//创建对应序列号的文件夹
        }
        for(int j =0;j<channels;++j){
            string url = data[i][2]+to_string(j);
            LOG_DEBUG(url.c_str());
            _lpool.addTask(new RecordVideo(url,cameraId,j,data[i][3]));

        }
    }

    _tcpServer.start();
}

void EchoServer::stop(){
    _pool.stop();
    _lpool.stop();
    _tcpServer.stop();
}

EchoServer::EchoServer(int thread_size,int task_size,uint16_t port,string ip )
    :_pool(thread_size,task_size)
    ,_lpool(24,task_size)
     ,_tcpServer(port,ip)
{
    _tcpServer.setAllCallBack(std::bind(&EchoServer::onConnect,this,std::placeholders::_1),
                              std::bind(&EchoServer::onMessage,this,std::placeholders::_1),
                              std::bind(&EchoServer::onClose,this,std::placeholders::_1)
                             );
}

